#pragma once
#include <type_traits>

namespace tpl
{
//template<typename... Args>
//struct IsCopyAssignable;
//std::is_copy_assignable<int>;
template <typename T>
using ops_t = decltype(std::declval<T&>() = std::declval<const T&&>());

//template <typename T, typename Op, typename U = std::void_t<>>
//struct Detect : std::false_type
//{
//};
//
//template <typename T, template <typename...> class Op>
//struct Detect<T, Op<T>, std::void_t<Op<T>>>
//  : std::is_same<Op<T>, T&>
//{
//};
//
//template<typename T>
//using IsCopyAssignable = Detect<T, decltype(std::declval<T&>() = std::declval<const T&&>())> ;


template <typename T, typename U = std::void_t<>>
struct IsCopyAssignable : std::false_type
{
};

template <typename T>
struct IsCopyAssignable<T, std::void_t<ops_t<T>>> : std::is_same<ops_t<T>, T&>
{
};

}